package com.yupi.project.manager;

import com.yupi.yuapicommon.model.common.BusinessException;
import com.yupi.yuapicommon.model.common.ErrorCode;
import org.redisson.Redisson;
import org.redisson.api.RRateLimiter;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateType;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Service
public class RedisLimiterManager {

    @Resource
    private RedissonClient redissonClient;

    /**
     * 限流操作
     * @param key 根据key区别不同的限流器
     * @return
     */
    public void doRateLimit(String key, int rate, int rateInterval, int rateIntervalUnit){
        // 1. 创建一个限流器
        RRateLimiter rateLimiter = redissonClient.getRateLimiter(key);
        // 3秒内最多1000个请求
        if(rateIntervalUnit == 1){
            rateLimiter.trySetRate(RateType.OVERALL,rate,rateInterval, RateIntervalUnit.MILLISECONDS);
        }else if(rateIntervalUnit == 2){
            rateLimiter.trySetRate(RateType.OVERALL,rate,rateInterval, RateIntervalUnit.SECONDS);
        } else if(rateIntervalUnit == 3){
            rateLimiter.trySetRate(RateType.OVERALL,rate,rateInterval, RateIntervalUnit.MINUTES);
        } else {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 2. 获取限流器里的令牌，每次请求消耗一个令牌
        //每当一个操作来了之后，请求一个令牌
        boolean canOp = rateLimiter.tryAcquire(1);
        if (canOp){
            // 成功获取令牌
        } else {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR);
        }
    }


    public static void main(String[] args){
        Config config=new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379").setDatabase(5);
        RedissonClient client= Redisson.create(config);

        RRateLimiter rateLimiter=client.getRateLimiter("rate_limiter1");
        rateLimiter.trySetRate(RateType.OVERALL,10,5, RateIntervalUnit.SECONDS);

        ExecutorService executorService= Executors.newFixedThreadPool(10);
        for (int i=0;i<1200;i++){
            int finalI = i;
            executorService.submit(()->{
                try{
                    rateLimiter.acquire(1);
                    System.out.println("thread:::"+ finalI + "---" + Thread.currentThread().getId());
                }catch (Exception e){
                    System.out.println("请求被限制啦！");
                    //e.printStackTrace();
                }
            });
        }
    }
}